# Observable’s not JavaScript

_A [@hpcc-js/observable-md](https://github.com/hpcc-systems/Visualization/tree/trunk/packages/observable-md) demo - these demos are currently a work in progress and have dependencies which may or may not exist at any given time..._

---
&uarr; <i class="fa fa-bug fa-lg" style="color:darkgray"></i> This document is best viewed with the "Show Developer Info" enabled above <i class="fa fa-bug fa-lg" style="color:darkgray"></i> &uarr;

---

At first glance, Observable appears to be vanilla JavaScript. This is intentional: by building on the native language of the web, Observable is more familiar and you can use the libraries you know and love, such as D3, Three, and TensorFlow. Yet for [dataflow](/@observablehq/how-observable-runs), Observable needed to change JavaScript in a few ways.

Here’s a quick overview of what’s different.

(We’ve also shared our [grammar](/@observablehq/observable-grammar) and [parser](https://github.com/observablehq/parser).)

### Cells are separate scripts.

Each cell in a notebook is a separate script that runs independently. A syntax error in one cell won’t prevent other cells from running.

```
This is English, not JavaScript.
```

Same with a runtime error.

```
{ throw new Error("oopsie"); }
```

Likewise, local variables are only visible to the cell that defines them.

```
{ var local = "I am a local variable."; }
```

### Cells run in topological order.

In vanilla JavaScript, code runs from top to bottom. Not so here; Observable runs [like a spreadsheet](/@observablehq/how-observable-runs), so you can define your cells in whatever order makes sense.

```
a + 2 // a is defined below
```

```
a = 1
```

By extension, circular definitions are not allowed.

```
c1 = c2 - 1
```

```
c2 = c1 + 1
```

### Cells re-run when any referenced cell changes.

You don’t have to run cells explicitly when you edit or interact—the notebook updates automatically. Run the cell below by clicking the play button <svg width="16" height="16" class="db bump" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round" fill="none"><path d="M4 3L12 8L4 13Z"></path></svg>, or by focusing and hitting Shift-Enter. Only the referencing cells run, then *their* referencing cells, and so on—other cells are unaffected.

```
b = Math.random()
```

```
b * b // updates automatically!
```

If a cell allocates resources that won’t be automatically cleaned up by the garbage collector, such as an animation loop or event listener, use the [invalidation promise](/@observablehq/invalidation) to dispose of these resources manually and avoid leaks.

```
{ invalidation.then(() => console.log("I was invalidated.")); }
```

### Cells implicitly await promises.

You can define a cell whose value is a promise.

```
hello = new Promise(resolve => {
  setTimeout(() => {
    resolve("hello there");
  }, 30000);
})
```

If you reference such a cell, you don’t need to await; the referencing cell won’t run until the value resolves.

```
c = {
  yield 1;
  yield 2;
  yield 3;
}
```

```
c
```

Also, yields occur no more than once every animation frame: typically sixty times a second, which makes generators handy for [animation](/@mbostock/animation-loops). If you yield a DOM element, it will be added to the DOM before the generator resumes.

### Named cells are declarations, not assignments.

Named cells look like, and function *almost* like, assignment expressions in vanilla JavaScript. But cells can be defined in any order, so think of them as hoisted function declarations.

```
foo = 2
```

You can’t assign the value of another cell (though see mutables below).

```
{ foo = 3; } // not allowed
```

Cell names must also be unique. If two or more cells share the same name, they will all error.

```
dup = 1
```

```
dup = 2
```

(Observable doesn’t yet support destructuring assignment to declare multiple names, but we hope to add that soon.)

### Statements need curly braces, and return (or yield).

A cell body can be a simple expression, such as a number or string literal, or a function call. But sometimes you want statements, such as for loops. For that you’ll need curly braces, and a return statement to give the cell a value. Think of a cell as a function, except the function has no arguments.

```
{
  let sum = 0;
  for (let i = 0; i < 10; ++i) {
    sum += i;
  }
  return sum;
}
```

For the same reason, you’ll need to wrap object literals in parentheses, or use a block statement with a return.

```
label = {foo: "bar"}
```

```
block = { return {foo: "bar"}; }
```

### Cells can be views.

Observable has a special [`viewof` operator](https://observablehq.com/@observablehq/introduction-to-views) which lets you define interactive values. A view is a cell with two faces: its user interface, and its programmatic value. Try editing the input below, and note that the referencing cell runs automatically.

```
viewof text = html`<input value="edit me">`
```

```
text
```

### Cells can be mutables.

Observable has a special [`mutable` operator](/@observablehq/introduction-to-mutable-state) so you can opt-in to mutable state: you can set the value of a mutable from another cell.

```
mutable thing = 0
```

```
++mutable thing // mutates thing
```

### Observable has a standard library.

Observable provides a small [standard library](https://github.com/observablehq/stdlib/blob/trunk/README.md) for essential features, such as Markdown tagged template literals and reactive width.

```
md`Hello, I’m *Markdown*!`
```

### Static ES imports are not supported; use dynamic imports.

Since everything in Observable is inherently dynamic, there’s not really a need for static ES imports—though, we might add support in the future. Note that only the most-recent browsers support dynamic imports, so you might consider using require for now.

```
_ = import("https://cdn.pika.dev/lodash-es/v4")
```

```
_.camelCase("lodash was here")
```

### require is AMD, not CommonJS.

[Observable’s require](/@observablehq/introduction-to-require) looks a lot like CommonJS because cells implicitly await promises. But under the hood it uses the [Asynchronous Module Definition (AMD)](https://requirejs.org/docs/whyamd.html). This convention will eventually be replaced with modern ES modules and imports, but it’s still useful for the present as many library authors are not yet shipping ES modules.

We recommend pinning major versions.

```
d3 = require("d3@5")
```
